<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>拖拽示例</title>
    <style>
        body {
            width: 2000px;
            height: 2000px;
        }

        #div {
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }
        #div2 {
            width: 100px;
            height: 100px;
            background-color: yellow;
            position: absolute;
            top:200px;
            left: 300px;
        }
    </style>
    <script type="text/javascript">
        window.onload = function () {
            let div = document.getElementById('div');
            bind(div, 'mousedown', function (event) {
                //鼠标点下的时候，相对位置就已经确定了
                event = event || window.event;
                let dy = event.clientY - div.offsetTop;
                let dx = event.clientX - div.offsetLeft;

                function documentMouseMove(event) {
                    event = event || window.event;
                    let x = event.clientX;
                    let y = event.clientY;
                    div.style.top = (y - dy) + 'px';
                    div.style.left = (x - dx) + 'px';
                }

                bind(document, 'mousemove', documentMouseMove);
                bind(document, 'mouseup', function () {
                    document.onmouseup = null;
                    removeBind(document, 'mousemove', documentMouseMove);
                });
                //浏览器有一个默认行为，当全选后，再去拖拽会存在问题
                //IE8上解决方式是设置setCapture()捕获,其它浏览器不支持火狐不报错，谷歌报错
                //捕获后也应该丢弃releaseCapture因为不丢失的话会影响其它行为
                return false;
            });

            /**
             * 绑定事件
             * 添加多个函数
             * @param obj 元素对象
             * @param eventStr 事件名不带on
             * @param callback 回调函数
             */
            function bind(obj, eventStr, callback) {
                if (obj.addEventListener) {
                    obj.addEventListener(eventStr, callback, false);
                } else {
                    obj.attachEvent('on' + eventStr, function () {
                        callback.call(obj);
                    });
                }
            }

            /**
             * 解除绑定事件，唯一不同就是传入想要解绑函数的名字，因为addEventListener添加函数可以为同一个事件
             * 添加多个函数
             * @param obj 元素对象
             * @param eventStr 时间名不带on
             * @param callbackName 函数名
             */
            function removeBind(obj, eventStr, callbackName) {
                if (obj.removeEventListener) {
                    obj.removeEventListener(eventStr, callbackName, false);
                } else {
                    obj.detachEvent('on' + eventStr, callbackName);
                }
            }
        }
    </script>
</head>
<body>
<div id="div"></div>
<div id="div2"></div>
</body>
</html>